<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>three辅助开发控件</title>
    <style>
        body {
            margin: 0;
        }
    </style>
</head>

<body>
    <script type="importmap">
        {
            "imports": {
                "three": "./build/three.module.js",
                "three/addons/": "./examples/jsm/"
            }
        }
    </script>
    <script type="module">
        import * as THREE from 'three';
        // 引入轨道控制器扩展库OrbitControls.js
        import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
        import Stats from 'three/addons/libs/stats.module.js';

        /**      一个3D 物体的形成需要
          *  1. 场景（Scene）承载物体的环境 const scene = new THREE.Scene()
          *  2. 相机（Camera）
          *  3. 渲染器（Renderer）
          * */

        /**
         *       场景中的物体（几何体）
         *   https://threejs.org/docs/index.html#api/en/geometries/BoxGeometry
        */
        /**
         *       几何体的外观（材质）
         *   https://threejs.org/docs/index.html?q=Material#api/en/materials/MeshBasicMaterial
        */

        // 画布大小
        const width = 800; //宽度
        const height = 500; //高度

        // 创建三维场景
        const scene = new THREE.Scene()

        // 添加辅助坐标轴
        const axesHelper = new THREE.AxesHelper(150);
        scene.add(axesHelper)

        // 创建三维中的物体
        const geometry = new THREE.BoxGeometry(100, 100, 100)
        const material = new THREE.MeshLambertMaterial({
            color: 0x00ffff, //设置材质颜色
            transparent: true,//开启透明
            opacity: 0.5,//设置透明度
        })
        const mesh = new THREE.Mesh(geometry, material)
        mesh.position.set(0, 0, 0)
        scene.add(mesh);

        // ------------------------------------------------------------------------
        // ------- 在三维场景中添加光源

        // 点光源
        // const pointLight = new THREE.PointLight(0xffffff, 1.0)  
        // pointLight.position.set(100, 100, 100);

        // 平行光
        const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
        directionalLight.position.set(100, 100, 100);
        // 方向光指向对象网格模型mesh，可以不设置，默认的位置是0,0,0
        directionalLight.target = mesh;
        scene.add(directionalLight);

        // ------ 添加光源辅助观察

        // 点光源
        // const pointLightHelper = new THREE.PointLightHelper(pointLight, 10);
        // scene.add(pointLightHelper);

        // 平行光
        const dirLightHelper = new THREE.DirectionalLightHelper(directionalLight, 10);
        scene.add(dirLightHelper);

        // -------------------------------------------------------------------------
        // 创建相机 拍摄物体
        const camera = new THREE.PerspectiveCamera(30, width / height, 1, 3000)
        camera.position.set(200, 300, 500)
        camera.lookAt(0, 0, 0)

        // 创建渲染器 呈现相机拍摄的场景
        const renderer = new THREE.WebGLRenderer()
        renderer.setSize(width, height);
        renderer.render(scene, camera);

        // ------ 创建相机控件轨道控制器OrbitControls
        /** 
         * 参数1 为哪一个相机添加控件
         * 参数2 相机监控的范围
        */
        const controls = new OrbitControls(camera, renderer.domElement);
        // 如果OrbitControls改变了相机参数，重新调用渲染器渲染三维场景
        controls.addEventListener('change', function () {
            renderer.render(scene, camera); //执行渲染操作
        });//监听鼠标、键盘事件

        // ------------------------------------------------------------------------
        // ------ 引入性能监视器
        //创建stats对象
        const stats = new Stats();
        //stats.domElement:web页面上输出计算结果,一个div元素，
        document.body.appendChild(stats.domElement);

        // 将渲染物体添加到 指代功能的元素中
        document.body.appendChild(renderer.domElement);

        // 渲染函数
        function render() {

            stats.update();           //requestAnimationFrame循环调用的函数中调用方法update(),来刷新时间

            renderer.render(scene, camera); //执行渲染操作

            mesh.rotateY(0.01);//每次绕y轴旋转0.01弧度

            requestAnimationFrame(render);//请求再次执行渲染函数render，渲染下一帧

        }

        render();

        /** 思路总结
          * 
        */
    </script>
</body>

</html>